package com.ctsi.commons.util.crypto;

import com.ctsi.commons.util.StringUtil;
import com.ctsi.commons.util.UtilValidate;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.FileInputStream;
import java.security.*;

/**
 * 数字签名
 * 
 * @author yueming
 * 
 */
public class SignatureUtil {
	private static final Logger log = LoggerFactory.getLogger(SignatureUtil.class);

	/**
	 * 签名
	 * 
	 * @param myprikey
	 *            私钥
	 * @param info
	 *            需要签名的信息
	 * @return 签名数据
	 */
	public static byte[] sign(PrivateKey myprikey, byte[] info, String signType) {
		try {

			// 用私钥对信息生成数字签名
			java.security.Signature signet = java.security.Signature.getInstance(signType);
			signet.initSign(myprikey);
			signet.update(info);
			byte[] signed = signet.sign(); // 对信息的数字签名
			if (log.isDebugEnabled()) {
				log.debug("signed(签名内容)={}", StringUtil.byte2hex(signed));
			}

			return signed;

		} catch (java.lang.Exception e) {
			log.error(e.toString());
			throw new RuntimeException(e);
		}

	}

	/**
	 * 
	 * @param pubkey
	 *            公钥
	 * @param info
	 *            验证信息
	 * @param signed
	 *            验证信息签名
	 * @return 结果
	 */
	public static boolean verify(PublicKey pubkey, byte[] info, byte[] signed, String signType) {

		try {

			log.debug("public key format:{}", pubkey.getFormat());

			java.security.Signature signetcheck = java.security.Signature.getInstance(signType);
			signetcheck.initVerify(pubkey);
			signetcheck.update(info);
			if (signetcheck.verify(signed)) {

				log.debug("sign ok");
				return true;
			} else {
				log.debug("sign error");
				return false;
			}

		} catch (Exception e)

		{
			log.error(e.toString());
			throw new RuntimeException(e);

		}
	}

	/*
	 * 获得私钥
	 */
	public static Key loadPrivateKey(String filename, String keyName, String pass, String provider) throws Exception {

		FileInputStream inKeyStoreFile = new FileInputStream(filename);
		try {
			char[] password = pass.toCharArray();
			KeyStore from;
			if (UtilValidate.isEmpty(provider)) {
				from = KeyStore.getInstance("JKS");
			} else {
				from = KeyStore.getInstance("JKS", provider);
			}

			from.load(inKeyStoreFile, password);
			Key testkey = from.getKey(keyName, password);
			return testkey;

		} catch (Exception e) {
			throw e;
		} finally {
			if (inKeyStoreFile != null)
				inKeyStoreFile.close();

		}

	}

	/*
	 * 获得公钥
	 */
	public static PublicKey loadPublicKey(String filename, String keyName, String pass, String provider) throws Exception {
		FileInputStream inKeyStoreFile = new FileInputStream(filename);

		try {
			KeyStore from;
			char[] password = pass.toCharArray();
			if (UtilValidate.isEmpty(provider)) {
				from = KeyStore.getInstance("JKS");
			} else {
				from = KeyStore.getInstance("JKS", provider);
			}

			from.load(inKeyStoreFile, password);
			java.security.cert.Certificate c = from.getCertificate(keyName);
			return c.getPublicKey();
		} catch (Exception e) {
			throw e;
		} finally {
			if (inKeyStoreFile != null)
				inKeyStoreFile.close();

		}

	}

	public static KeyPair genKeyPair(String signType, int size, Provider provider) throws NoSuchAlgorithmException {
		KeyPairGenerator rsaKeyGen = null;
		KeyPair rsaKeyPair = null;
		if (UtilValidate.isEmpty(signType)) {
			signType = "RSA";
		}
		if (size % 64 != 0) {
			log.warn("size {} % 64!=0 ", size);
		}
		log.info("Generator {} key ,size {}", signType, size);
		if (provider != null)
			rsaKeyGen = KeyPairGenerator.getInstance(signType, provider);
		else
			rsaKeyGen = KeyPairGenerator.getInstance(signType);
		SecureRandom random = new SecureRandom();
		random.nextBytes(new byte[1]);
		rsaKeyGen.initialize(size, random);
		rsaKeyPair = rsaKeyGen.genKeyPair();

		return rsaKeyPair;
	}
}
